package com.objectmentor.a.clientserver_1;

import java.net.Socket;
import org.junit.After;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import common.Logger;
import common.LoggingUtil;
import common.MessageUtils;

public class ServerTest {
    Logger logger = LoggingUtil.getLoggerFor(getClass());
    private static final int PORT = 8009;
    private static final int TIMEOUT = 100;

    Server server;
    Thread serverThread;

    @BeforeClass
    public static void uncommentToSeeTrace() {
        LoggingUtil.enableDebuTrace();
    }

    @Before
    public void createServer() throws Exception {
        try {
            ClientProcessorFactory factory = new SocketBasedClientProcessorFactory(PORT, TIMEOUT);
            server = new Server(factory);
            serverThread = new Thread(server);
            serverThread.start();
        } catch (Exception e) {
            e.printStackTrace(System.err);
            throw e;
        }
    }

    @After
    public void shutdownServer() throws InterruptedException {
        if (server != null) {
            server.stopProcessing();
            serverThread.join();
        }
    }

    class TrivialClient implements Runnable {
        int clientNumber;

        TrivialClient(int clientNumber) {
            this.clientNumber = clientNumber;
        }

        public void run() {
            connectSendReceive(clientNumber);
        }
    }

    @Test(timeout = 10000)
    public void shouldRunInUnder10Seconds() throws Exception {
        Thread[] threads = new Thread[100];
        for (int i = 0; i < threads.length; ++i) {
            threads[i] = new Thread(new TrivialClient(i));
            threads[i].start();
        }

        for (int i = 0; i < threads.length; ++i) {
            threads[i].join();
        }
    }

    private void connectSendReceive(int i) {
        try {
            logger.debug("%d: connecting", i);
            Socket socket = new Socket("localhost", PORT);
            logger.debug("%d: sending message", i);
            MessageUtils.sendMessage(socket, Integer.toString(i));
            logger.debug("%d: getting reply", i);
            MessageUtils.getMessage(socket);
            logger.debug("%d: finished", i);
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
